﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using Jint.Native;
using Jint;

namespace jsweb
{
   class Session
   {
      private readonly HttpListenerContext _context;
      public JsObject SessionObj;
      private static RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider();

      /// <summary>
      /// Decrypts and initializes the session if valid (invalidates during server restart)
      /// </summary>
      /// <param name="context"></param>
      /// <param name="jsEngine"></param>
      public Session(HttpListenerContext context, JintEngine jsEngine)
      {
         _context = context;

         // Initialize session
         if (context.Request.Cookies["jsSESSION"] != null)
         {
            string cookieBase64 = context.Request.Cookies["jsSESSION"].Value;
            byte[] base64 = Convert.FromBase64String(cookieBase64);

            // Try to decrypt session
            try
            {
               byte[] decrypted = _rsa.Decrypt(base64, true);
               string cookieStr = Encoding.UTF8.GetString(decrypted);
               SessionObj = jsEngine.Run("eval((" + cookieStr + "));") as JsObject;
            }
            catch (Exception)
            {
               SessionObj = new JsObject();
            }
         }
         else
         {
            SessionObj = new JsObject();
         }

         // Register session object
         jsEngine.SetParameter("Session", SessionObj);
      }

      /// <summary>
      /// Saves the session to a cookie
      /// </summary>
      public void Save()
      {
         // Serialize cookie and encrypt
         byte[] encrypted = _rsa.Encrypt(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(SessionObj)), true);
         string base64String = Convert.ToBase64String(encrypted);
         Cookie cookie = new Cookie("jsSESSION", base64String);
         _context.Response.Cookies.Add(cookie);
      }
   }
}
